
#include "bsp_lin_driver.h"


#if(LIN_USED == TRUE)


/* (CLK (MHz)* timer period (us) / Prescaler) */
#define TIMER_COMPARE_VAL             (uint16_t)(2000U)
#define TIMER_TICKS_1US               (uint16_t)(4U)
#define DATA_SIZE                     (8U)
#define FRAME_SLAVE_RECEIVE_DATA      (1U)
#define FRAME_MASTER_RECEIVE_DATA     (2U)
#define FRAME_GO_TO_SLEEP             (3U)
#define TIMEOUT                       (500U)

static lin_callback_t CallbackHandler(uint32_t instance, lin_state_t * lin1_State);

uint16_t timerOverflowInterruptCount = 0U;
volatile uint16_t capturedValue = 0U;
volatile bool linEnabled = false;
volatile bool wakeupSignalFlag = false;

uint8_t rxBuff[DATA_SIZE] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t sw_version_buff[8] = {0x14, 0x1A, 0xC, 0x1A, 0x56, 0x1, 0x2E, 0x1};
uint8_t sw_version_buff2[8] = {0x43, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};

extern EventGroupHandle_t xEventGroup;

void Bsp_LIN_Init(void)
{

    /* Initialize LIN network interface */
    LIN_DRV_Init(INST_LIN1, &lin1_InitConfig0, &lin1_State);
    /* Install callback function */
    LIN_DRV_InstallCallback(INST_LIN1, (lin_callback_t)CallbackHandler);
}

uint32_t lin1TimerGetTimeIntervalCallback0(uint32_t *ns)
{
    static uint32_t previousCountValue = 0UL;
    uint32_t counterValue;
    counterValue = capturedValue;
    *ns = ((uint32_t)(counterValue + timerOverflowInterruptCount * TIMER_COMPARE_VAL - previousCountValue)) * 1000UL / TIMER_TICKS_1US;
    timerOverflowInterruptCount = 0UL;
    previousCountValue = counterValue;

    return 0UL;
}


static lin_callback_t CallbackHandler(uint32_t instance, lin_state_t * lin1_State)
{
    lin_callback_t callbackCurrent;
    callbackCurrent = lin1_State->Callback;
    (void)instance;

    switch (lin1_State->currentEventId)
    {
        case LIN_PID_OK:

            /* Set timeout */
            LIN_DRV_SetTimeoutCounter(INST_LIN1, 500U);

			if(0x1 == lin1_State->currentId)
            {
                /* Call to Send Frame DATA Function */
                LIN_DRV_SendFrameData(INST_LIN1, sw_version_buff, sizeof(sw_version_buff));
                LIN_DRV_ReceiveFrameData(INST_LIN1, rxBuff, sizeof(rxBuff));
            }

			if(0x2 == lin1_State->currentId)
            {
                /* Call to Send Frame DATA Function */
                LIN_DRV_SendFrameData(INST_LIN1, sw_version_buff2, sizeof(sw_version_buff2));
            }

            break;
        case LIN_PID_ERROR:
            /* Go to idle mode */
            LIN_DRV_GoToSleepMode(INST_LIN1);
            break;
        case LIN_TX_COMPLETED:
        case LIN_RX_COMPLETED:
            /* Go to idle mode */
            LIN_DRV_GotoIdleState(INST_LIN1);
            break;
        case LIN_CHECKSUM_ERROR:
        case LIN_READBACK_ERROR:
        case LIN_FRAME_ERROR:
        case LIN_RECV_BREAK_FIELD_OK:
            /* Set timeout */
            LIN_DRV_SetTimeoutCounter(INST_LIN1, 500);
            break;
        case LIN_WAKEUP_SIGNAL:
            break;
        case LIN_SYNC_ERROR:
        case LIN_BAUDRATE_ADJUSTED:
        case LIN_NO_EVENT:
        case LIN_SYNC_OK:
        default:
        /* do nothing */
            break;
    }

    return callbackCurrent;
}

void lin_slave_task(void)
{
    uint8_t index;
    uint8_t byteRemain = 1U;
    bool receiveFlag = false;
    status_t status = STATUS_ERROR;

    linEnabled = true;

    status = LIN_DRV_GetReceiveStatus(INST_LIN1, &byteRemain);

    if((status == STATUS_SUCCESS) && (0U == byteRemain) && (FRAME_SLAVE_RECEIVE_DATA == lin1_State.currentId))
    {
        if(rxBuff[0] == 0x2)
        {
            receiveFlag = true;
        }

        /* Check data receiving */
        if (receiveFlag)
        {
            xEventGroupSetBits(xEventGroup, EVENRGROUP_LIGHT_SHOW);
        }
    }

    /* Check node state */
    if (LIN_NODE_STATE_SLEEP_MODE == LIN_DRV_GetCurrentNodeState(INST_LIN1))
    {

    }
}

#endif
